# coding:utf8
import copy

from appserver import db_store
from sqlalchemy.orm import relationship, backref
from sqlalchemy import or_
from models.entity.district_with_device import DistrictWithDevice
from models.entity.device_with_sensor import DeviceWithSensor
from models.entity.device_type import DeviceType
from models.entity.district import District
from models.entity.tree_model_base import TreeModelBase


"""
设备表
"""


class Device(TreeModelBase):
    __tablename__ = "devices"
    __bind_key__ = "main"

    # autoincrement=True,
    id = db_store.Column(db_store.Integer, primary_key=True, comment=u'设备编号')
    name = db_store.Column(db_store.String(64), nullable=False, unique=True, comment=u'设备名称')
    code = db_store.Column(db_store.String(32), nullable=False, unique=True, comment=u"设备编码")
    description = db_store.Column(db_store.String(255), default="", nullable=False, comment=u"描述")
    device_type_id = db_store.Column(db_store.Integer, db_store.ForeignKey('device_types.id'), comment=u"设备分类id")
    device_group_id = db_store.Column(db_store.Integer, db_store.ForeignKey("device_groups.id"), comment=u"设备分组id")
    parent_id = db_store.Column(db_store.Integer, nullable=False, comment=u"父ID")
    path = db_store.Column(db_store.String(255), nullable=False, comment=u"路径")
    depth = db_store.Column(db_store.Integer, comment=u"深度")
    child_num = db_store.Column(db_store.Integer, comment=u"子类数量")
    dis_order = db_store.Column(db_store.Integer, comment=u"排序")
    icon = db_store.Column(db_store.String(32), comment=u"图标")
    lat = db_store.Column(db_store.Float, comment=u"经度")
    lng = db_store.Column(db_store.Float, comment=u"纬度")
    status = db_store.Column(db_store.Integer, comment=u"状态")  # 1-正常 0-禁用(异常)
    start_time=db_store.Column(db_store.DateTime,comment=u"启动时间")
    valid_time=db_store.Column(db_store.Integer,comment=u"设备有效时间") # 整数,单位是天
    DeviceType = relationship("DeviceType", backref=backref('devices', order_by=id))

    def __repr__(self):
        return "<Device %s>" % self.name

    def save(self):
        try:
            print('device,保存')
            if self.id == 0:  # 新增数据
                self.id = self.get_max_id() + 1
                self.path = str(self.id)
                self.depth = len(self.path.split(','))
                self.child_num = 0
            db_store.session.add(self)
            db_store.session.commit()
            return True
        except Exception as err:
            print(err)
            db_store.session.rollback()
            return False

    def from_dict(self, rev_source):
        source = copy.deepcopy(rev_source)
        # print('source', source)
        # if "parent_id" in source:
        # Instance '<District at 0x7f28901badd8>' has been deleted, or its row is otherwise not present.
        # 下面的方法引起的错误
        # source["parent_id"] = source.pop("parent_id") #
        # source["parent_id"] = source.get("parent_id")
        # if "level" in source:
        #     source["depth"] = source.pop("level")
        if "district_id" in source:
            source.pop("district_id")
        if "level" in source:
            source.pop("level")
        if "sensors" in source:
            source.pop("sensors")
        if "data_type" in source:
            source.pop("data_type")

        for k in source:
            # print('k',k)
            try:
                getattr(self, k)
                # print('getattr',getattr(self, k))
            except AttributeError as e:
                print(e)
                raise RuntimeError("数据格式错误")
            setattr(self, k, source[k])
            # print('setattr',setattr(self, k, source[k]))
        
    def to_dict(self):
        from models.entity.device_group import DeviceGroup
        rdic={}
        rdic["data_type"]=3
        rdic["id"]=self.id
        rdic["name"]=self.name
        rdic["code"]=self.code
        rdic["description"]=self.description
        rdic["status"]=self.status
        rdic["parent_id"]=self.parent_id
        rdic["level"]=self.depth
        if self.start_time is None:
            rdic["start_time"]=""
        else:
            rdic["start_time"]=self.start_time.strftime("%Y-%m-%d")
        rdic["device_type_id"]=self.device_type_id
        rdic["device_type_name"]=DeviceType.get_device_type_by_id(self.device_type_id).name
        rdic["device_group_id"]=self.device_group_id
        rdic["device_group_name"]=DeviceGroup.get_device_group_by_id(self.device_group_id).name
        rdic["lat"]=self.lat
        rdic["lng"]=self.lng
        rdic["dis_order"]=self.dis_order
        rdic["icon"]=self.icon
        rdic["valid_time"]=self.valid_time
        rdic["sensors"]=[]   # 给字典添加一个建,存放传感器列表
        sensor_connectors=DeviceWithSensor.query.filter_by(device_id=self.id).all()
        for item in sensor_connectors:
            rdic["sensors"].append(item.sensor_id)
        district_connector=DistrictWithDevice.query.filter_by(device_id=self.id).first()
        if district_connector is not None:  # 字典中添加分区id和分区name
            rdic["district_id"]=district_connector.district_id
            rdic["device_district_name"]=District.query.filter_by(id=district_connector.district_id).first().name
        else:
            rdic["district_id"]=None
            rdic["device_district_name"]=None
        return rdic

    @staticmethod
    def get_device_all():
        return Device.query.order_by("dis_order").all()

    @staticmethod
    def get_device_by_id(id_num):
        return Device.query.filter_by(id=id_num).first()

    @staticmethod
    def get_device_by_name(name):
        return Device.query.filter_by(name=name).first()

    @staticmethod
    def get_device_by_code(code):
        return Device.query.filter_by(code=code).first()

    @staticmethod
    def get_device_by_parent_id(parent_id):
        return Device.query.filter_by(parent_id=parent_id).first()

    @staticmethod
    def get_devices_by_type_id(device_type_id):
        return Device.query.filter_by(device_type_id=device_type_id).all()
    
    @staticmethod
    def get_devices_by_group_id(group_id):
        return Device.query.filter_by(device_group_id=group_id).all()
    
    @staticmethod
    def get_devices_by_district_id(id_num):
        connectors=DistrictWithDevice.query.filter_by(district_id=id_num).all()
        rlist=[]
        for item in connectors:
            rlist.append(Device.query.filter_by(id=item.device_id).first())
        return rlist

    @staticmethod
    def search(query_word):
        data = []
        devices = Device.query.filter(
            or_(Device.code.like('%' + query_word + '%'), Device.name.like('%' + query_word + '%'),
                Device.description.like('%' + query_word + '%'))).all()
        for obj in devices:
            data.append(obj.to_dict())
        return data

